#!perl
use strict;
use Data::Dumper;
use File::Basename;
use Cwd 'abs_path';
use Digest::MD5 qw(md5 md5_hex md5_base64);
use lib '/homes/smandal/work/dcg/om/graph';
use JNPR::Utils;
my $g_sql_out = [];

my $g_cachedir = '../../cache';

my $bindir = abs_path(dirname($0));
my $db = "$bindir/db";

for my $branch (<STDIN>) {
    chomp $branch;
    $branch =~ s{[\s/]*$}{};
    $branch =~ s{^[\s/]*}{};
    # We don't do trunk. Too expensive.
    next if ($branch eq 'trunk');
    doit($branch);
}


#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub doit
{
    my ($branch) = @_;

    my $dot = '';
    log_time('print_requested_branch', $branch, \$dot);
    log_time('print_parentage', $branch, \$dot);
    log_time('print_merges_to_me', $branch, \$dot);
    log_time('print_merges_from_me', $branch, \$dot);
    log_time('print_branch_pulls_from_me', $branch, \$dot);
    print $dot;
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
{
my $oldbranch;
sub log_time
{
    my ($fn_name, @args) = @_;
    my $fn_ptr = eval "\\&$fn_name";
    my $before = time;
    &{$fn_ptr}(@args);
    my $after = time;

    my $timespent = $after - $before;
    my $args = join ', ', @args;
    my $branch = $args[0];
    if ($oldbranch ne $branch) {
        $oldbranch = $branch;
        print STDERR "\n";
    }
    print STDERR "$fn_name($args) : $timespent\n";
}
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub print_requested_branch
{
    my ($branch, $out) = @_;
    $$out .=
          "requested_branches {\n"
        . "$branch\n"
        . "}\n\n"
        ;
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub print_branch_pulls_from_me
{
    my ($branch, $out) = @_;
    my $cmd = ''
            . 'SELECT branch_name FROM '
            . 'branches WHERE '
            . "parent_branch_name = \"$branch\"; "
            ;
    my @child_branches = ();
    JNPR::Utils::sql_query($db, \$cmd, \@child_branches);
    my $digest = md5_hex(join '', @child_branches);

    my $newdot = '';
    if (-e "$g_cachedir/branch_pulls_from_me/$branch/$digest") {
        open F, "<$g_cachedir/branch_pulls_from_me/$branch/dot.txt" or die;
        {
            local $/;
            undef $/;
            $newdot = <F>;
        }
        close F;
    }
    else {
        for my $child_branch (@child_branches) {
            chomp $child_branch;
            print_parentage($child_branch, \$newdot);
        }
        if (-d "$g_cachedir/branch_pulls_from_me/$branch") {
            system "/bin/rm -rf '$g_cachedir/branch_pulls_from_me/$branch'";
        }
        system "mkdir -p '$g_cachedir/branch_pulls_from_me/$branch'";
        open F, ">$g_cachedir/branch_pulls_from_me/$branch/dot.txt" or die;
        print F $newdot;
        close F;

        open F, ">$g_cachedir/branch_pulls_from_me/$branch/$digest" or die;
        close F;
    }
    $$out .= $newdot;
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub print_merges_from_me
{
    my ($branch, $out) = @_;
    my $cmd = ''
            . 'SELECT from_rev,to_rev FROM '
            . 'merges INNER JOIN nodes '
            . 'ON '
            . "branch = \"$branch\" AND from_rev = rev;"
            ;
    my @arrows = ();
    JNPR::Utils::sql_query($db, \$cmd, \@arrows);
    my $arrows = join '', @arrows;
    print STDERR $arrows;
    my $digest = md5_hex($arrows);

    my $newdot = '';
    if (-e "$g_cachedir/merges_from_me/$branch/$digest") {
        open F, "<$g_cachedir/merges_from_me/$branch/dot.txt" or die;
        {
            local $/;
            undef $/;
            $newdot = <F>;
        }
        close F;
    }
    else {
        for my $arrow (@arrows) {
            chomp $arrow;
            my ($from_rev, $to_rev) = split /\|/, $arrow;
            my $to_branch = JNPR::Utils::get_branch_of_rev($db,$to_rev);
            print_parentage($to_branch, \$newdot);
            $newdot .=
                  "merges {\n"
                . "$branch\@$from_rev -> $to_branch\@$to_rev\n"
                . "}\n\n"
                ;
        }
        if (-d "$g_cachedir/merges_from_me/$branch") {
            system "/bin/rm -rf '$g_cachedir/merges_from_me/$branch'";
        }
        system "mkdir -p '$g_cachedir/merges_from_me/$branch'";
        open F, ">$g_cachedir/merges_from_me/$branch/dot.txt" or die;
        print F $newdot;
        close F;

        open F, ">$g_cachedir/merges_from_me/$branch/$digest" or die;
        close F;
    }
    $$out .= $newdot;
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
sub print_merges_to_me
{
    my ($branch, $out) = @_;

    my $query = ''
     . "select branch,from_rev,date,to_rev,to_date from "
     . "nodes "
     . "inner join "
     . "( "
     .     "select from_rev,to_rev,to_date from "
     .     "merges "
     .     "inner join "
     .     "( "
     .         "select rev,date as to_date from nodes "
     .         "where branch = \"$branch\" "
     .     ") "
     .     "on rev = to_rev "
     . ") "
     . "on rev = from_rev;\n"
     ;


    JNPR::Utils::sql_query($db, \$query, $g_sql_out);
    my @output = map {chomp; $_} @$g_sql_out;
        #  'IB_11_3_FST_BRANCH|425558|2011-02-16 16:11:24 -0800|425651|2011-02-17 02:43:41 -0800',
        #  'IB_11_3_FST_BRANCH|425155|2011-02-15 00:06:38 -0800|425586|2011-02-16 19:02:52 -0800',
        #  'trunk|423833|2011-02-07 17:24:35 -0800|425148|2011-02-14 23:42:17 -0800',
        #  'trunk|421349|2011-01-22 11:39:21 -0800|422980|2011-02-01 19:31:54 -0800',
        #  'trunk|420192|2011-01-14 06:06:35 -0800|422687|2011-01-31 12:01:44 -0800',
        #  'trunk|420135|2011-01-13 21:01:45 -0800|421986|2011-01-26 22:12:04 -0800',
        #  'trunk|419560|2011-01-10 18:59:39 -0800|419971|2011-01-12 18:24:57 -0800',
        #  'trunk|417226|2010-12-22 09:45:17 -0800|417925|2010-12-29 18:06:41 -0800',
        #  'trunk|415609|2010-12-13 19:41:37 -0800|416324|2010-12-16 14:43:14 -0800',
        #  'trunk|414463|2010-12-07 06:04:43 -0800|414586|2010-12-07 14:49:30 -0800',
        #  'trunk|414084|2010-12-04 15:11:32 -0800|414563|2010-12-07 12:43:14 -0800',
        #  'IB5_11_2_BRANCH|412455|2010-11-24 10:33:56 -0800|412783|2010-11-27 12:27:18 -0800',
        #  'DEV_FX_SI_BRANCH|411172|2010-11-17 16:58:48 -0800|411184|2010-11-17 19:00:55 -0800',
        #  'DEV_FX_SI_BRANCH|410627|2010-11-15 11:32:23 -0800|411095|2010-11-17 11:26:26 -0800',
        #  'DEV_FX_SI_BRANCH|408649|2010-11-04 01:18:45 -0700|408992|2010-11-05 17:11:04 -0700',
        #  'DEV_FX_SI_BRANCH|407183|2010-10-27 13:19:07 -0700|407266|2010-10-27 18:25:20 -0700'

    my $digest = md5_hex(join '', @output);
    my $newdot = '';
    if (-e "$g_cachedir/merges_to_me/$branch/$digest") {
        open F, "<$g_cachedir/merges_to_me/$branch/dot.txt" or die;
        {
            local $/;
            undef $/;
            $newdot = <F>;
        }
        close F;
    }
    else {
        for my $output (@output) {
            my ($from_branch, $from_rev, $from_date, $to_rev, $to_date) = split /\|/, $output;
            my $from_branch_full_name      = JNPR::Utils::branch_full_name($db, $from_branch, $from_rev);
            my $branch_full_name           = JNPR::Utils::branch_full_name($db, $branch, $to_rev);
            $newdot .=
                  "{\n"
                . "$from_branch_full_name\n"
                . "$from_rev|$from_date\n"
                . "}\n"
                . "\n"
                . "{\n"
                . "$branch_full_name\n"
                . "$to_rev|$to_date\n"
                . "}\n"
                . "\n"
                . "merges {\n"
                . "$from_branch\@$from_rev -> $branch\@$to_rev\n"
                . "}\n"
                . "\n"
                ;
            print_parentage($from_branch, \$newdot);
        }
        if (-d "$g_cachedir/merges_to_me/$branch") {
            system "/bin/rm -rf '$g_cachedir/merges_to_me/$branch'";
        }
        system "mkdir -p '$g_cachedir/merges_to_me/$branch'";
        open F, ">$g_cachedir/merges_to_me/$branch/dot.txt" or die;
        print F $newdot;
        close F;

        open F, ">$g_cachedir/merges_to_me/$branch/$digest" or die;
        close F;
    }
    $$out .= $newdot;
}

#
# --------------------------------------------------------------------
# --------------------------------------------------------------------
{
my $done_parentage;
sub print_parentage
{
    my ($branch, $out) = @_;

    return if($branch eq 'trunk');
    $done_parentage = {} unless (defined $done_parentage);
    return if (exists $done_parentage->{$branch});

    my $cmd;

    $cmd = 'select branch_name,creation_rev,parent_branch_name,parent_branch_rev '
         . "from branches where branch_name = \"$branch\""
         ;
    # sqlite -column -header ~/db \
    # 'select * from branches where branch_name = "IB5_10_3_BRANCH";'
    # branch_name      creation_rev  parent_branch_name  parent_branch_rev
    # ---------------  ------------  ------------------  -----------------
    # IB5_10_3_BRANCH  331617        trunk               331363           
    # IB5_10_3_BRANCH  346512        trunk               344064           
    # IB5_10_3_BRANCH  349965        trunk               348657           
    # IB5_10_3_BRANCH  354560        trunk               353410           
    # IB5_10_3_BRANCH  360235        trunk               358618           

    my @branch_incarnations = ();
    JNPR::Utils::sql_query($db, \$cmd, \@branch_incarnations);

    for my $branch_incarnation (@branch_incarnations) {
        chomp $branch_incarnation;
        my ($branch_name,
            $creation_rev,
            $parent_branch_name,
            $parent_branch_rev) = split /\|/, $branch_incarnation;

        $cmd = "select date from nodes where rev = $creation_rev;\n";
        JNPR::Utils::sql_query($db, \$cmd, $g_sql_out);
        my $child_date = $g_sql_out->[0];
        chomp $child_date;

        $cmd = "select date from nodes where rev = $parent_branch_rev;\n";
        JNPR::Utils::sql_query($db, \$cmd, $g_sql_out);
        my $parent_date = $g_sql_out->[0];
        chomp $parent_date;

        my $parent_branch_full_name = JNPR::Utils::branch_full_name($db, $parent_branch_name, $parent_branch_rev);
        #if ($branch_full_name ne '@') {
            $$out .=
                  "{\n"
                . "$branch_name\@$creation_rev\n"
                . "$creation_rev|$child_date\n"
                . "}\n\n"
                . "{\n"
                . "$parent_branch_full_name\n"
                . "$parent_branch_rev|$parent_date\n"
                . "}\n\n"
                . "parentage {\n"
                . "$parent_branch_rev -> $branch_name\@$creation_rev\n"
                . "}\n\n";
            $done_parentage->{"$branch_name\@$creation_rev"} = 1;
        #}
        if ($parent_branch_name ne '') {
            print_parentage($parent_branch_name, $out);
        }
    }
}

}


__END__
sqlite db .schema
#CREATE TABLE branches (branch_name TEXT, creation_rev INTEGER PRIMARY KEY, parent_branch_name TEXT, parent_branch_rev INTEGER);
#CREATE TABLE counts (svn_hi_rev INTEGER,svn_lo_rev INTEGER,nodes_hi_rev INTEGER,nodes_lo_rev INTEGER,branches_hi_rev INTEGER,branches_lo_rev INTEGER,merges_hi_rev INTEGER,merges_lo_rev INTEGER);
#CREATE TABLE merges (merge_id INTEGER PRIMARY KEY AUTOINCREMENT, from_rev INTEGER, to_rev INTEGER );
#CREATE TABLE nodes (rev INTEGER PRIMARY KEY NOT NULL, author TEXT, date TEXT, branch TEXT);

select rev from nodes where branch = "DEV_FX_SI_BRANCH"

select
    *
from
    (
    select 
        from_rev,to_rev
    from
        (
        select rev from nodes where branch = "DEV_FX_SI_TMP_BRANCH"
        )
    inner join
        merges
    on
        from_rev = rev
    )
inner join
    nodes
on
    rev in (to_rev)
;

sqlite -header -column db 'select branch_name, count(branch_name) as n from branches group by branch_name having n > 1 order by n desc'
